package cn.stylefeng.guns.modular.gridsystem.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.text.StrFormatter;
import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.guns.core.exception.ServiceException;
import cn.stylefeng.guns.core.factory.PageFactory;
import cn.stylefeng.guns.core.pojo.page.PageResult;
import cn.stylefeng.guns.modular.gridsystem.entity.BizChannelType;
import cn.stylefeng.guns.modular.gridsystem.entity.BizDevice;
import cn.stylefeng.guns.modular.gridsystem.entity.BizGatewayChannel;
import cn.stylefeng.guns.modular.gridsystem.entity.BizThreholdItem;
import cn.stylefeng.guns.modular.gridsystem.enums.ChannelExceptionEnum;
import cn.stylefeng.guns.modular.gridsystem.mapper.BizChannelTypeMapper;
import cn.stylefeng.guns.modular.gridsystem.mapper.BizDeviceMapper;
import cn.stylefeng.guns.modular.gridsystem.mapper.BizGatewayChannelMapper;
import cn.stylefeng.guns.modular.gridsystem.model.param.BizGatewayChannelParam;
import cn.stylefeng.guns.modular.gridsystem.model.param.BizThreholdItemParam;
import cn.stylefeng.guns.modular.gridsystem.model.result.BizGatewayChannelResult;
import cn.stylefeng.guns.modular.gridsystem.service.BizGatewayChannelService;
import cn.stylefeng.guns.modular.gridsystem.service.BizThreholdItemService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * biz_gateway_channel 服务实现类
 *
 * @author ssy
 * @date 2021/09/14 11:47
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class BizGatewayChannelServiceImpl extends ServiceImpl<BizGatewayChannelMapper, BizGatewayChannel> implements BizGatewayChannelService {

    private final BizGatewayChannelMapper bizGatewayChannelMapper;

    private final BizThreholdItemService bizThreholdItemService;

    private final BizChannelTypeMapper channelTypeMapper;

    private final BizDeviceMapper deviceMapper;

    @Override
    public PageResult<BizGatewayChannel> page(BizGatewayChannelParam bizGatewayChannelParam) {

        // 构造条件
        LambdaQueryWrapper<BizGatewayChannel> queryWrapper = new LambdaQueryWrapper<>();
        if (ObjectUtil.isNotNull(bizGatewayChannelParam)) {
            if (ObjectUtil.isNotEmpty(bizGatewayChannelParam.getGatewayId())) {
                queryWrapper.eq(BizGatewayChannel::getGatewayId, bizGatewayChannelParam.getGatewayId());
            }
        }
        // 查询分页结果
        return new PageResult<>(this.page(PageFactory.defaultPage(), queryWrapper));
    }

    @Override
    public List<BizGatewayChannelResult> list(BizGatewayChannelParam bizGatewayChannelParam) {

        // 构造条件
        LambdaQueryWrapper<BizGatewayChannel> queryWrapper = new LambdaQueryWrapper<>();
        if (ObjectUtil.isNotEmpty(bizGatewayChannelParam)) {
            if (ObjectUtil.isNotEmpty(bizGatewayChannelParam.getGatewayId())) {
                queryWrapper.eq(BizGatewayChannel::getGatewayId, bizGatewayChannelParam.getGatewayId());
            }
            if (ObjectUtil.isNotEmpty(bizGatewayChannelParam.getDeviceId())) {
                queryWrapper.eq(BizGatewayChannel::getDeviceId, bizGatewayChannelParam.getDeviceId());
            }
        }

        List<BizGatewayChannelResult> channels = this.list(queryWrapper).stream()
                .map(item -> BeanUtil.toBean(item, BizGatewayChannelResult.class))
                .collect(Collectors.toList());

        List<Integer> channelTypeIds = channels.stream().map(BizGatewayChannelResult::getChannelType).collect(Collectors.toList());

        if (!channelTypeIds.isEmpty()) {

            List<BizChannelType> channelTypeList = channelTypeMapper.selectList(new LambdaUpdateWrapper<BizChannelType>()
                    .in(ObjectUtil.isNotEmpty(channelTypeIds), BizChannelType::getId, channelTypeIds));

            for (BizGatewayChannelResult channel : channels) {
                List<BizChannelType> channelTypes = channelTypeList.stream().filter(item -> item.getId().equals(channel.getChannelType())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(channelTypes)) {
                    channel.setChannelTypeCode(channelTypes.get(0).getCode());
                }
            }
        }


        return channels;
    }

    @Override
    public List<BizGatewayChannelResult> listChannel(BizGatewayChannelParam param) {

        return this.list(new LambdaQueryWrapper<BizGatewayChannel>()
                .eq(ObjectUtil.isNotEmpty(param.getGatewayId()), BizGatewayChannel::getGatewayId, param.getGatewayId()))
                .stream()
                .map(item -> BeanUtil.toBean(item, BizGatewayChannelResult.class))
                .collect(Collectors.toList());
    }

    @Override
    public void add(BizGatewayChannelParam bizGatewayChannelParam) {

        // 将dto转为实体
        BizGatewayChannel bizGatewayChannel = new BizGatewayChannel();
        BeanUtil.copyProperties(bizGatewayChannelParam, bizGatewayChannel);
        final boolean save = this.save(bizGatewayChannel);
        if(save){
            bizGatewayChannelParam.setId(bizGatewayChannel.getId());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(BizGatewayChannelParam bizGatewayChannelParam) {
        //删除通道对应的阈值
        final LambdaQueryWrapper<BizThreholdItem> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BizThreholdItem::getGatewayChannel, bizGatewayChannelParam.getChannel());
        queryWrapper.eq(BizThreholdItem::getGatewayId, bizGatewayChannelParam.getGatewayId());
        bizThreholdItemService.remove(queryWrapper);

        this.removeById(bizGatewayChannelParam.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean edit(BizGatewayChannelParam bizGatewayChannelParam) {

        // 根据id查询实体
        BizGatewayChannel bizGatewayChannel = this.queryBizGatewayChannel(bizGatewayChannelParam);
        Integer id = bizGatewayChannel.getId();
        BizGatewayChannel gatewayChannel = this.getById(id);
        Integer gatewayId = gatewayChannel.getGatewayId();
        BizThreholdItemParam bizThreholdItemParam = new BizThreholdItemParam();
        bizThreholdItemParam.setGatewayId(gatewayId);
        bizThreholdItemParam.setGatewayChannel(bizGatewayChannel.getChannel());
        BizThreholdItem bizThreholdItem = bizThreholdItemService.threholdItemByChannelAndGatewayId(bizThreholdItemParam);
        if (bizThreholdItem != null) {
            UpdateWrapper<BizThreholdItem> wrapper = new UpdateWrapper<>();
            wrapper.set("gateway_channel", bizGatewayChannelParam.getChannel());
            wrapper.eq("id", bizThreholdItem.getId());
            bizThreholdItemService.update(wrapper);
        }
        // 请求参数转化为实体
        BeanUtil.copyProperties(bizGatewayChannelParam, bizGatewayChannel);
        bizGatewayChannelParam.setId(id);
        return this.updateById(bizGatewayChannel);
    }

    @Override
    public BizGatewayChannel detail(BizGatewayChannelParam bizGatewayChannelParam) {
        return this.queryBizGatewayChannel(bizGatewayChannelParam);
    }

    /**
     * 通过网关id列表
     *
     * @return {@link BizGatewayChannel}
     */
    @Override
    public BizGatewayChannel listByGatewayId(Integer gatewayId, String micRouter) {
        LambdaQueryWrapper<BizGatewayChannel> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BizGatewayChannel::getGatewayId, gatewayId);
        queryWrapper.eq(BizGatewayChannel::getChannel, micRouter);
        return bizGatewayChannelMapper.selectOne(queryWrapper);
    }

    @Override
    public List<BizGatewayChannelResult> listByGId(BizGatewayChannelParam bizGatewayChannelParam) {
        return this.baseMapper.listByGId(bizGatewayChannelParam);
    }

    @Override
    public PageResult<BizGatewayChannelResult> pageList(BizGatewayChannelParam param) {
        return new PageResult<>(this.baseMapper.pageList(PageFactory.defaultPage(), param));
    }

    @Override
    public Integer countByDIdAndChannel(BizGatewayChannelParam param) {
        return this.baseMapper.countByDIdAndChannel(param);
    }

    @Override
    public BizGatewayChannel gatewayChannelByGIdAndChannel(BizGatewayChannelParam param) {
        LambdaQueryWrapper<BizGatewayChannel> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BizGatewayChannel::getChannel, param.getChannel());
        queryWrapper.eq(BizGatewayChannel::getGatewayId, param.getGatewayId());
        return this.getOne(queryWrapper);
    }

    @Override
    public Integer getChannelCount(List<Integer> gatewayIds) {
        QueryWrapper<BizGatewayChannel> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("gateway_id", gatewayIds);
        return this.count(queryWrapper);
    }

    @Override
    public void editById(BizGatewayChannelParam param) {
        // 根据id查询实体
        BizGatewayChannel bizGatewayChannel = this.queryBizGatewayChannel(param);
        // 请求参数转化为实体
        BeanUtil.copyProperties(param, bizGatewayChannel);
        this.updateById(bizGatewayChannel);
    }

    @Override
    public void unbinding(BizGatewayChannelParam param) {

        BizGatewayChannel channel = getById(param.getId());

        if (ObjectUtil.isEmpty(channel)) {
            log.warn("通道不存在，通道主键为：{}", param.getId());
            throw new ServiceException(ChannelExceptionEnum.NOT_EXIST);
        }

        // 通道解绑
        update(new LambdaUpdateWrapper<BizGatewayChannel>()
                .eq(BizGatewayChannel::getId, channel.getId())
                .set(BizGatewayChannel::getDeviceId, null)
                .set(BizGatewayChannel::getPositionType, null)
                .set(BizGatewayChannel::getXposion, 0)
                .set(BizGatewayChannel::getYposion, 0));

    }

    @Override
    public void mark(BizGatewayChannelParam param) {

        BizGatewayChannel channel = getById(param.getId());

        if (ObjectUtil.isEmpty(channel)) {
            log.warn("通道不存在，通道主键为：{}", param.getId());
            throw new ServiceException(ChannelExceptionEnum.NOT_EXIST);
        }

        channel.setGatewayId(param.getGatewayId());
        channel.setDeviceId(param.getDeviceId());
        channel.setXposion(param.getXposion());
        channel.setYposion(param.getYposion());
        channel.setPositionType(param.getPositionType());
        updateById(channel);

    }

    @Override
    public String queryChannelBindingInfo(BizGatewayChannelParam param) {

        BizGatewayChannel channel = getById(param.getId());

        if (ObjectUtil.isEmpty(channel)) {
            log.warn("通道不存在，通道主键为：{}", param.getId());
            throw new ServiceException(ChannelExceptionEnum.NOT_EXIST);
        }

        if (ObjectUtil.isEmpty(channel.getDeviceId())) {
            log.warn("通道未绑定其它设备，通道主键为：{}", param.getId());
            throw new ServiceException(ChannelExceptionEnum.NOT_BINDING_DEVICE);
        }

        BizDevice device = deviceMapper.selectById(channel.getDeviceId());

        if (ObjectUtil.isEmpty(device)) {
            log.warn("设备不存在，设备主键为：{}", channel.getDeviceId());
            throw new ServiceException(ChannelExceptionEnum.DEVICE_NOT_EXIST);
        }

        return StrFormatter.format("此通道已绑定在设备{}上，确定解绑吗？", device.getDeviceName());

    }

    @Override
    public BizGatewayChannel gatewayChannelByCodeAndChannel(BizGatewayChannelParam param) {


        return this.baseMapper.gatewayChannelByCodeAndChannel(param);
    }

    /**
     * 获取biz_gateway_channel
     *
     * @author ssy
     * @since 2021/09/14 11:47
     */
    private BizGatewayChannel queryBizGatewayChannel(BizGatewayChannelParam bizGatewayChannelParam) {
        BizGatewayChannel bizGatewayChannel = this.getById(bizGatewayChannelParam.getId());
        return bizGatewayChannel;
    }
}
